package netty.rpc.core;

import javafx.util.Pair;
import netty.rpc.client.RpcInterfaceProxy;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 注解解析器
 * @author Jim
 * @version 1.0.0
 * @descripition:
 * @date 2022/5/21 23:27
 */
public class NettyRpcAnnotationScanner {

    private List<String> commonMethods;

    private NettyRpcAnnotationScanner(){
        commonMethods = new ArrayList<>();
        commonMethods.add("wait");
        commonMethods.add("equals");
        commonMethods.add("toString");
        commonMethods.add("hashCode");
        commonMethods.add("getClass");
        commonMethods.add("notify");
        commonMethods.add("notifyAll");
    }

    static class Singleton{
       private static NettyRpcAnnotationScanner INSTANCE = new NettyRpcAnnotationScanner();
    }

    public static NettyRpcAnnotationScanner getInstance(){
        return Singleton.INSTANCE;
    }

    /**
     * 根据注解和服务名生成待注册服务模型描述
     * @param bean
     * @param serviceDefinition
     * @return
     */
    public InterfaceDefinition scan(Object bean,ServiceDefinition serviceDefinition){
        Class<?> clazz = bean.getClass();
        Class<?>[] interfaces = clazz.getInterfaces();
        NettyRpcInterface rpcInterface = null;
        for (Class aClass:interfaces){
            Annotation[] annotations = aClass.getAnnotations();
            for (Annotation annotation:annotations){
                if (annotation instanceof NettyRpcInterface){
                    rpcInterface = (NettyRpcInterface) annotation;
                    break;
                }
            }
        }
        if (rpcInterface == null){
            return null;
        }

        //待注册的Interfaces
        if (serviceDefinition.getServiceName().equals(rpcInterface.value())){

            InterfaceDefinition interfaceDefinition = new InterfaceDefinition();
            String interfaceName = rpcInterface.interfaceClass().getName();

            long timeOut = rpcInterface.timeOut();
            boolean enable = rpcInterface.enable();
            Method[] methods = clazz.getMethods();

            for (Method method:methods){
                String methodName = method.getName();
                if (commonMethods.contains(methodName)){
                    continue;
                }
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (parameterTypes != null && parameterTypes.length > 0){
                    List<String> parameterList = new ArrayList<>(parameterTypes.length);
                    for (Class parameterClass:parameterTypes){
                        String parameterName = parameterClass.getName();
                        parameterList.add(parameterName);
                        MethodDefinition methodDefinition = new MethodDefinition();
                        methodDefinition.setMethodName(methodName);
                        methodDefinition.setParameterTypes(parameterList);

                        interfaceDefinition.getMethodDefinitionList().add(methodDefinition);
                    }
                }


            }

            interfaceDefinition.setInterfaceName(interfaceName);
            interfaceDefinition.setTimeOut(timeOut);
            interfaceDefinition.setInterfaceEnabled(enable);

            return interfaceDefinition;
        }
        return null;
    }

}
